﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EasyTrader.Manager
{
    public class PureHogaSummitSysManager : SysManager
    {

        #region Member Variables
        private EasyTrader.Wave.PriceWave m_CurBuyWave = null;
        private EasyTrader.Wave.PriceWave m_CurSellWave = null;
        //private int m_BuyDayHigh = 0;
        //private int m_SellDayHigh = 0;
        #endregion
        // 이 함수는 현재 상태가 상승인지 하락인지 판단을 한다. 새로운 상태가 나오면 새로운 상태를 등록한다.
        // 호가 정점에서 평균값으로 일정개수를 내려오면 상태를 전환시켜 준다.
        private void FindCurState()
        {
            //return m_TotalSigMan.FindState(m_SysType, m_FirstSig, m_PriceStateList, m_LogFileName, ref m_CurState);

            // 시스템 상태를 확인한다.
            EasyTrader.Signal.PriceSignal curState = FindSysState();
            // 시스템 상태가 바뀌었을 경우 확인하고 신호정보를 복사하여 추가한다.
            m_TotalSigMan.CheckAddState(m_TotalSigMan.CurIndex, m_PriceStateList, curState);
        }

        private EasyTrader.Signal.PriceSignal FindSysState()
        {
            if (m_PriceStateList.Count == 0)
            {
                return m_TotalSigMan.FindFirstSignalBySysType(GlobalVar.SysTypeHogaSummit, HogaSummitSysVar.FirstSignalType, m_LogFileName, ref m_CurState);
            }

            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);
            double curVal = m_TotalSigMan.CurVal;
            if (curVal == 0.0)
                return null;

            double dayAmp = m_TotalSigMan.GetDayAmp();
            // 현재 파동을 가져온다.
            EasyTrader.Wave.PriceWave curWave = m_TotalSigMan.ETWaveSignalManager.EasyTraderWaveManager.GetCurWave(m_TotalSigMan.CurIndex);
            if (curWave == null)
                return null;

            // 먼저 이전 신호에 대하여 대응을 해준다.
            if (lastState.Type == GlobalVar.SignalBuy)
            {
                double lastLowY = lastState.SignalMin;
                double limitLowVal = lastLowY - 0.15;
                if (curWave.Slope == GlobalVar.PriceDown && curVal < limitLowVal)
                {
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매수로청산(돌파)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }
            else if (lastState.Type == GlobalVar.SignalSell)
            {
                double lasthighY = lastState.SignalMax;
                double limitHighVal = lasthighY + 0.15;
                if (curWave.Slope == GlobalVar.PriceUp && curVal > limitHighVal)
                {
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitSell, GlobalVar.SignalStateLiquid, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매도로청산(돌파)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }


            // 최소 진폭에서는 반응하지 않는다.
            if (dayAmp <= PureHogaSummitSysVar.MinTurnHeight)
                return null;

            // 평균값을 얻기 위해 차트 데이터를 설정해 준다. 
            if (GlobalVar.OperationMode == GlobalVar.OperationModeNormal)
            {
                m_TotalSigMan.ETHogaSignalManager.SetChartData(m_TotalSigMan.EasyTraderDataSet, PureHogaSummitSysVar.MinAveVal);
            }
            else
            {
                m_TotalSigMan.ETHogaSignalManager.SetChartData(m_TotalSigMan.CurIndex, m_TotalSigMan.EasyTraderDataSet, PureHogaSummitSysVar.MinAveVal);
            }

            // 평균값을 적용한 매수와 매도의 평균값을 가져온다.
            double curBuyVal = m_TotalSigMan.ETHogaSignalManager.GetBuyAveVal();
            double curSellVal = m_TotalSigMan.ETHogaSignalManager.GetSellAveVal();
            int lowBuy = 0;
            int lowSell = 0;

            // 당일 매수와 매도의 최고가를 가져온다.
            m_TotalSigMan.BuyDayHigh = m_TotalSigMan.ETHogaSignalManager.GetBuyDayHigh(m_TotalSigMan.CurIndex, ref lowSell);
            m_TotalSigMan.SellDayHigh = m_TotalSigMan.ETHogaSignalManager.GetSellDayHigh(m_TotalSigMan.CurIndex, ref lowBuy);

            // 당일 최고값과 평균값 사이의 차이를 구한다.
            int deltaBuy = m_TotalSigMan.BuyDayHigh - Convert.ToInt32(curBuyVal);
            int deltaSell = m_TotalSigMan.SellDayHigh - Convert.ToInt32(curSellVal);
            // 차이가 일정개수를 넘어가지 않으면 아무일도 하지 않는다.
            if (lastState.Type == GlobalVar.SignalSell)
            {
                if (lastState.SellDayHigh < m_TotalSigMan.SellDayHigh && deltaSell < PureHogaSummitSysVar.MinTurnHogaDelta)
                    return null;
            }
            if (lastState.Type == GlobalVar.SignalBuy)
            {
                if (lastState.BuyDayHigh < m_TotalSigMan.BuyDayHigh && deltaBuy < PureHogaSummitSysVar.MinTurnHogaDelta)
                    return null;
            }

            // 매수와 매도의 파동을 찾아 각 파동의 최고 최소를 구한다.
            double sellAveMin = 0.0, sellAveMax = 0.0;
            double buyAveMin = 0.0, buyAveMax = 0.0;
            m_CurBuyWave = m_TotalSigMan.ETHogaSignalManager.FindBuyWave(m_TotalSigMan.CurIndex);
            m_CurSellWave = m_TotalSigMan.ETHogaSignalManager.FindSellWave(m_TotalSigMan.CurIndex);

            // 파동의 최소, 최대값을 구한다.
            m_TotalSigMan.ETHogaSignalManager.FindBuyWaveHighLow(m_CurBuyWave);
            m_TotalSigMan.ETHogaSignalManager.FindSellWaveHighLow(m_CurSellWave);
            if (m_CurBuyWave == null || m_CurSellWave == null)
                return null;
            // 파동의 평균값의 최소 최대를 구한다.
            m_TotalSigMan.ETHogaSignalManager.FindSellWaveAveHighLow(m_CurSellWave, ref sellAveMax, ref sellAveMin);
            m_TotalSigMan.ETHogaSignalManager.FindBuyWaveAveHighLow(m_CurBuyWave, ref buyAveMax, ref buyAveMin);
            // 상대 파동에 대한 차이를 구한다.
            double minMaxDelta = 0.0;
            if (buyAveMax > sellAveMax)
            {
                minMaxDelta = buyAveMax - sellAveMin;
            }
            else if (sellAveMax > buyAveMax)
            {
                minMaxDelta = sellAveMax - buyAveMin;
            }

            // 두번째 상태가 되었을 때부터 이 부분을 적용해 준다.
            if (m_PriceStateList.Count >= 2)
            {
                // 먼저 이전 신호에 대하여 대응을 해준다.
                if (lastState.Type == GlobalVar.SignalBuy)
                {
                    // 매도 파동이 하락하고 매수 파동이 상승하는 상황
                    if (m_CurSellWave.Slope == GlobalVar.PriceUp && m_CurBuyWave.Slope != GlobalVar.PriceUp)
                    {
                        double deltaWave = Math.Abs(m_CurSellWave.HighY - m_CurBuyWave.LowY);
                        if (m_CurSellWave.LowY < m_CurBuyWave.HighY && deltaWave >= PureHogaSummitSysVar.MinLiquidHogaDelta)
                        {
                            m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                            m_TotalSigMan.WriteStateLog("매수로 청산", m_LogFileName, m_CurState);
                            return m_CurState;
                        }
                    }
                }
                else if (lastState.Type == GlobalVar.SignalSell)
                {
                    if (m_CurBuyWave.Slope == GlobalVar.PriceUp && m_CurSellWave.Slope != GlobalVar.PriceUp)
                    {
                        double deltaWave = Math.Abs(m_CurBuyWave.HighY - m_CurSellWave.LowY);
                        if (m_CurBuyWave.LowY < m_CurSellWave.HighY && deltaWave >= PureHogaSummitSysVar.MinLiquidHogaDelta)
                        {
                            m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitSell, GlobalVar.SignalStateLiquid, ref m_CurState);
                            m_TotalSigMan.WriteStateLog("매도로 청산", m_LogFileName, m_CurState);
                            return m_CurState;
                        }
                    }
                }
            }


            // 두 파동이 일정한 높이를 가지지 않으면 아무일도 하지 않는다.
            // 그리고 2시 30이후에는 전환 신호를 받지 않는다.
            if (minMaxDelta <= PureHogaSummitSysVar.MinTurnHogaMaxMinDelta || m_TotalSigMan.CurIndex > PureHogaSummitSysVar.LastIndex)
                return null;

            // 호가로 인한 신호는 청산가능 건수보다 작을 때만 낸다.
            // 이 신호는 호가 우위의 영향을 받지 않는다.
            if (m_CurBuyWave.HighY > m_CurSellWave.HighY && m_TotalSigMan.BuyDayHigh > lowSell && m_TotalSigMan.BuyDayHigh > lastState.BuyDayHigh && deltaBuy > PureHogaSummitSysVar.MinTurnHogaDelta)
            {
                if (m_CurBuyWave.Slope == GlobalVar.PriceDown && m_CurSellWave.Slope == GlobalVar.PriceUp)
                {
                    if (lastState.Type != GlobalVar.SignalSell)
                    {
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateOver, ref m_CurState);
                        m_TotalSigMan.WriteStateLog("매도로상태전환(일반)", m_LogFileName, m_CurState);
                        return m_CurState;
                    }
                }
            }

            if (m_CurBuyWave.HighY < m_CurSellWave.HighY && m_TotalSigMan.SellDayHigh > lowBuy && m_TotalSigMan.SellDayHigh > lastState.SellDayHigh && deltaSell > PureHogaSummitSysVar.MinTurnHogaDelta)
            {
                if (m_CurSellWave.Slope == GlobalVar.PriceDown && m_CurBuyWave.Slope == GlobalVar.PriceUp)
                {
                    if (lastState.Type != GlobalVar.SignalBuy)
                    {
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                        m_TotalSigMan.WriteStateLog("매수로상태전환(일반)", m_LogFileName, m_CurState);
                        return m_CurState;
                    }
                }
            }

            return null;
        }

        // 상태를 바탕으로 신호를 발생시킨다.
        private void CheckSignal()
        {
            if (PureHogaSummitSysVar.LastSignalFired == true)
                return;

            // 먼저 상태 개수를 확인한다.
            // 정해진 상태 개수 안에서만 신호를 발생시킨다.
            int stateCount = m_PriceStateList.Count;
            if (stateCount < PureHogaSummitSysVar.SysStartState ||
                stateCount > PureHogaSummitSysVar.SysEndState)
                return;

            // 먼저 청산을 확인한다.
            // 가격에 의한 청산 신호가 있는지 확인한다.
            EasyTrader.Signal.PriceSignal curSignal = GetLiquidSignalByTotalPrice();
            EasyTrader.Signal.PriceSignal activeSignal = null;
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                PureHogaSummitSysVar.AutoOrder = false;
                PureHogaSummitSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(PureHogaSummitSysVar.AutoOrder, GlobalVar.SysTypePureHogaSummit);
            }

            curSignal = GetLiquidSignalByMaxPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                PureHogaSummitSysVar.AutoOrder = false;
                PureHogaSummitSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(PureHogaSummitSysVar.AutoOrder, GlobalVar.SysTypeJisuWaveHogaSummit);
            }

            curSignal = GetLiquidSignalByTotalPriceStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                // 단계별 총 청산액을 증가시켜 준다.
                PureHogaSummitSysVar.TotalProfitStepLiquidVal += PureHogaSummitSysVar.StepLiquidVal;
            }

            curSignal = GetLiquidSignalByStateCountStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                // 단계별 상태값을 증가시켜 준다.
                PureHogaSummitSysVar.StepLiquidStateCount++;
            }

            curSignal = GetLiquidSignalByPerPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
            }
            // 시간에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByTime();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                PureHogaSummitSysVar.AutoOrder = false;
                PureHogaSummitSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(PureHogaSummitSysVar.AutoOrder, GlobalVar.SysTypePureHogaSummit);
            }
            // 상태 개수에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByStateCount();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                PureHogaSummitSysVar.AutoOrder = false;
                PureHogaSummitSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(PureHogaSummitSysVar.AutoOrder, GlobalVar.SysTypePureHogaSummit);
            }
            // 상태 전환에 의한 신호가 있는지 확인한다.
            curSignal = GetSignalByStateChange();
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
            }
        }

        public void UpdateSysState()
        {
            FindCurState();
            CheckSignal();
        }
    }
}
